/**
 * 校验位计算工具库
 * 支持 Mod 10 (Luhn) 和 Mod 11 算法
 */

/**
 * Mod 10 校验位（Luhn 算法）
 * 适用于：银行卡号、IMEI、GS1 条码（如 GTIN）、信用卡等
 *
 * 规则：
 * 从右往左数，偶数位乘 2（若 ≥10 则各位相加），奇数位不变，总和 mod 10，补足到 10 的倍数
 * 或理解为：从左往右，位置权重交替为 1 和 2（基于总长度奇偶性调整）
 *
 * @param {string} number - 数字字符串（不含校验位）
 * @returns {number} 校验位（0-9）
 */
export function mod10(number) {
  let sum = 0;

  for (let i = 0; i < number.length; i++) {
    const digit = parseInt(number[i], 10);
    const isEvenPosition = (i + number.length) % 2 === 0;

    if (isEvenPosition) {
      // 偶数位：直接加
      sum += digit;
    } else {
      // 奇数位：乘 2，若结果 >= 10，则各位相加（如 8*2=16 → 1+6=7）
      const doubled = digit * 2;
      sum += doubled >= 10 ? doubled - 9 : doubled;
      // 或：sum += Math.floor(doubled / 10) + (doubled % 10);
    }
  }

  return (10 - (sum % 10)) % 10;
}

/**
 * Mod 11 校验位（加权模 11）
 * 适用于：ISBN-10、中国身份证（部分系统）、阿根廷 CUIT 等
 *
 * 规则：
 * 从右往左，依次使用权重 [2,3,4,5,6,7] 循环加权求和
 * 校验位 = (11 - sum % 11) % 11
 * 特殊：若结果为 10，某些系统用 'X' 表示；为 11 则为 0
 *
 * @param {string} number - 数字字符串（不含校验位）
 * @returns {number} 校验位（0-10），10 通常表示为 'X'
 */
export function mod11(number) {
  const weights = [2, 3, 4, 5, 6, 7];
  let sum = 0;

  for (let i = 0; i < number.length; i++) {
    const digit = parseInt(number[number.length - 1 - i], 10); // 从右往左取
    const weight = weights[i % weights.length];
    sum += digit * weight;
  }

  const remainder = sum % 11;
  return (11 - remainder) % 11; // 结果范围：0-10
}